from django.db import transaction
from rest_framework import serializers

from spits.models import spits, spits_comment, spits_Like, spits_collection, spits_comment_Like
from users.models import User


class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ('id', 'username')


class SpitSerializer(serializers.ModelSerializer):
    """吐槽列表序列化器"""
    user = UserSerializer(read_only=True)

    class Meta:
        model = spits
        fields = ('id', 'content', 'create_time', 'sp_like_count', 'user')


class SpitCommentSeriazer(serializers.ModelSerializer):
    """吐槽评论序列器"""
    user_id = UserSerializer()

    class Meta:
        model = spits_comment
        fields = ('id', 'user_id', 'content', 'like_count', 'create_time', 'parent_id')


class SpitSubmitSerializer(serializers.ModelSerializer):
    class Meta:
        model = spits
        fields = ('content',)

    def create(self, validated_data):
        # user_id = validated_data['user_id']
        user = self.context['request'].user

        content = validated_data['content']

        with transaction.atomic():
            try:
                save_id = transaction.savepoint()
                spit = spits.objects.create(
                    content=content,
                    user_id=user
                )

                spit.save()
            except Exception as e:
                transaction.savepoint_rollback(save_id)
                raise
            else:
                transaction.savepoint_commit(save_id)

        return spit


class SpitLikeSerializer(serializers.ModelSerializer):
    class Meta:
        model = spits_Like
        fields = ('spit_id',)


class SpitLikeActionSerializer(serializers.ModelSerializer):
    """点赞取消点赞序列化器"""
    action = serializers.CharField(label='点赞', write_only=True)

    class Meta:
        model = spits_Like
        fields = ('spit_id', 'action')

    def validate_action(self, value):
        """检验用户是否同意协议"""
        if value not in ['add', 'cancel']:
            raise serializers.ValidationError('数据传输错误')
        return value


class SpitCollectionSerializer(serializers.ModelSerializer):
    class Meta:
        model = spits_collection
        fields = ('spit_id',)


class SpitCollectionActionSerializer(serializers.ModelSerializer):
    """收藏取消收藏序列化器"""
    action = serializers.CharField(label='点赞', write_only=True)

    class Meta:
        model = spits_Like
        fields = ('spit_id', 'action')

    def validate_action(self, value):
        """检验用户是否同意协议"""
        if value not in ['add', 'cancel']:
            raise serializers.ValidationError('数据传输错误')
        return value


class SpitCommentLikeSerializer(serializers.ModelSerializer):
    """获取评论点赞信息序列化器"""
    class Meta:
        model = spits_comment_Like
        fields = ('comment_id',)


class SpitCommentLikeActionSerializer(serializers.ModelSerializer):
    """吐槽评论点赞序列化器"""
    action = serializers.CharField(label='点赞', write_only=True)

    class Meta:
        model = spits_comment_Like
        fields = ('comment_id', 'action')

    def validate_action(self, value):
        """检验用户是否同意协议"""
        if value not in ['add', 'cancel']:
            raise serializers.ValidationError('数据传输错误')
        return value


class SpitCommentCreateSerializer(serializers.ModelSerializer):
    class Meta:
        model = spits_comment_Like
        fields = ('spit_id', 'content')

    def create(self, validated_data):
        user = self.context['request'].user
        spit_id = validated_data['spit_id']
        content = validated_data['content']
        with transaction.atomic():
            try:
                save_id = transaction.savepoint()
                spit_comment = spits_comment_Like.objects.create(
                    content=content,
                    user_id=user,
                    spit_id=spit_id
                )

                spit_comment.save()
            except Exception as e:
                transaction.savepoint_rollback(save_id)
                raise
            else:
                transaction.savepoint_commit(save_id)

        return spit_comment